package com.ctshk.rpc.order.season.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.*;
import com.ctshk.common.model.TokenUser;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.common.utils.SnowflakeIdWorker;
import com.ctshk.rpc.booking.enums.SupplierReserveTypeEnum;
import com.ctshk.rpc.booking.req.system.admission.add.SupplierOrderSystemAdmissionAddReq;
import com.ctshk.rpc.booking.req.system.admission.add.SupplierSystemOrderAdmissionTicketAddReq;
import com.ctshk.rpc.booking.req.system.admission.add.SupplierSystemOrderAdmissionTicketDetailAddReq;
import com.ctshk.rpc.booking.service.ISupplierOrderService;
import com.ctshk.rpc.iotc.dto.OperateBankPreferenceQueryDTO;
import com.ctshk.rpc.iotc.req.OperateBankConformQueryReq;
import com.ctshk.rpc.iotc.service.IOperateBankPreferenceService;
import com.ctshk.rpc.iotc.service.IOperatePromotionService;
import com.ctshk.rpc.order.scenic.req.ScenicAddCheckOrderReq;
import com.ctshk.rpc.order.scenic.req.ScenicOrderInputCheckReq;
import com.ctshk.rpc.order.scenic.req.ScenicOrderTouristInputCheckReq;
import com.ctshk.rpc.order.scenic.req.ScenicPayOrderCollectionReq;
import com.ctshk.rpc.order.scenic.service.IScenicOrderService;
import com.ctshk.rpc.order.season.dto.SeasonOrderPayDTO;
import com.ctshk.rpc.order.season.dto.SeasonOrderTouristDataDTO;
import com.ctshk.rpc.order.season.dto.SeasonProductOrderScenicDTO;
import com.ctshk.rpc.order.season.entity.SeasonOrder;
import com.ctshk.rpc.order.season.entity.SeasonProductOrderScenic;
import com.ctshk.rpc.order.season.mapper.SeasonOrderMapper;
import com.ctshk.rpc.order.season.mapper.SeasonProductOrderScenicMapper;
import com.ctshk.rpc.order.season.service.ISeasonOrderTouristService;
import com.ctshk.rpc.order.season.service.ISeasonProductOrderScenicService;
import com.ctshk.rpc.scenic.dto.ScenicProductPriceListDTO;
import com.ctshk.rpc.scenic.req.ScenicProductPriceListReq;
import com.ctshk.rpc.scenic.service.IScenicProductService;
import com.ctshk.rpc.season.service.ISeasonDynamicProductPackageService;
import com.ctshk.rpc.system.dto.UserDTO;
import com.ctshk.rpc.system.dto.member.CrmAccountDTO;
import com.ctshk.rpc.system.req.crm.member.CrmMemberQueryReq;
import com.ctshk.rpc.system.service.ICrmMemberService;
import com.ctshk.rpc.system.service.ISysUserService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * <p>
 * 套票-订单-景点门票订单 服务实现类
 * </p>
 *
 * @author 杨林
 * @since 2021-03-24
 */
@DubboService
public class SeasonProductOrderScenicServiceImpl extends ServiceImpl<SeasonProductOrderScenicMapper, SeasonProductOrderScenic> implements ISeasonProductOrderScenicService {


    @Autowired
    private SeasonProductOrderScenicMapper orderScenicMapper;

    @Autowired
    private SeasonOrderMapper seasonOrderMapper;

    @Autowired
    private ISeasonOrderTouristService seasonOrderTouristService;

    @DubboReference
    private ISupplierOrderService supplierOrderService;

    @DubboReference
    private ISeasonDynamicProductPackageService packageService;

    @DubboReference
    private IOperateBankPreferenceService iOperateBankPreferenceService;

    @DubboReference
    private ISysUserService iSysUserService;
    @DubboReference
    private IOperatePromotionService iOperatePromotionService;
    @DubboReference
    private IScenicOrderService scenicOrderService;
    @DubboReference
    private ICrmMemberService crmMemberService;
    @DubboReference
    private IScenicProductService scenicProductService;


    /* @MethodName: 保存景点门票订单信息
     * @Description: TODO
     * @Param:
     * @Return:
     * @Author: 杨林
     * @Date:2021/3/25 9:31
     **/
    @Override
    public void saveScenicProduct(List<SeasonProductOrderScenicDTO> scenicList, Long userId, Long orderId) {
        LocalDateTime now = LocalDateTime.now();
        List<SeasonProductOrderScenic> list = scenicList.stream().map(
                scenicReq -> {
                    SeasonProductOrderScenic scenic = EntityUtil.copy(scenicReq, SeasonProductOrderScenic.class);
                    scenic.setCreateId(userId);
                    scenic.setGmtCreate(now);
                    scenic.setIsDeleted(IsDeletedCode.NO.getCode());
                    scenic.setSeasonOrderId(orderId);
                    scenic.setId(SnowflakeIdWorker.nextId());
                    return scenic;
                }
        ).collect(Collectors.toList());

        orderScenicMapper.insertBatchSomeColumn(list);
    }

    /* @MethodName: 景点门票 订单信息
     * @Description: TODO
     * @Param:
     * @Return:
     * @Author: 杨林
     * @Date:2021/3/30 16:47
     **/
    @Override
    public List<SeasonProductOrderScenicDTO> getOrderScenicList(Long id) {
        List<SeasonProductOrderScenicDTO> resultList = EntityUtil.copyList(
                orderScenicMapper.selectList(
                        new QueryWrapper<SeasonProductOrderScenic>().lambda()
                                .eq(SeasonProductOrderScenic::getSeasonOrderId, id)
                                .eq(SeasonProductOrderScenic::getIsDeleted, IsDeletedCode.NO.getCode())

                ), SeasonProductOrderScenicDTO.class);

        return resultList;
    }

    /* @MethodName: 景点门票下供应商预订单
     * @Description: TODO
     * @Param:
     * @Return:
     * @Author: 杨林
     * @Date:2021/4/7 18:17
     **/
    @Override
    public void playSupplierOrder(Long orderId, TokenUser tokenUser) {
        UserDTO user = iSysUserService.getUser(new UserDTO().setUsername(tokenUser.getUsername()));
        List<SeasonProductOrderScenicDTO> dtoList = getOrderScenicList(orderId);
        SeasonOrder seasonOrder = getSeasonOrderById(orderId);
        for (SeasonProductOrderScenicDTO scenicDTO : dtoList) {
            SupplierOrderSystemAdmissionAddReq admissionAddReq = new SupplierOrderSystemAdmissionAddReq();
            //订单类型
            admissionAddReq.setOrderType(1);
            //供应商ID不能为空
            admissionAddReq.setSupplierId(scenicDTO.getSupplierId());
            //供应商名称
            admissionAddReq.setSupplierName(scenicDTO.getSupplierName());
            //供应商订单类型不能为空 1:普通订单,2:内部挂账订单
            admissionAddReq.setSupplierOrderType("2");
            //供应商销售编号/部门ID(根据'供应商订单编号'显示，1：供应商销售编号，2：部门ID)
            admissionAddReq.setOriginalSaleNumber(String.valueOf(user.getDeptId()));
            //业务类型不能为空
            admissionAddReq.setBusinessType(SystemBusinessType.TRAIN_TICKET.getCode());
            //预订类型
            admissionAddReq.setReserveTypeId(SupplierReserveTypeEnum.TRAIN.getId());
            //产品类型
            admissionAddReq.setProductType(ProductType.MANUAL_ENTRY.getCode());
            //资源所属部门ID
            admissionAddReq.setDepartmentId(user.getDeptId());
            //资源所属部门
            admissionAddReq.setDepartment(user.getDept());

            //销售单号
            admissionAddReq.setSaleNumber(seasonOrder.getOrderNumber());
            //产品编号(通用)
            admissionAddReq.setProductNumber(String.valueOf(scenicDTO.getProductId()));
            //产品名称
            admissionAddReq.setProductNumber(seasonOrder.getProductName());

            //总金额
            admissionAddReq.setTotalFee(seasonOrder.getOrderAmount());
            //币种id
            admissionAddReq.setCurrencyId(Currency.HKD.getCode());
            //币种
            admissionAddReq.setCurrency(Currency.HKD.getCurrency());
            //应付金额不能为空
            admissionAddReq.setPayableAmount(seasonOrder.getReceivableAmount());
            //付款类型ID不能为空
            //hotelReq.setPayTypeId();
            List<SupplierSystemOrderAdmissionTicketAddReq> ticketAddReqList = new LinkedList<>();
            SupplierSystemOrderAdmissionTicketAddReq ticketAddReq = new SupplierSystemOrderAdmissionTicketAddReq();
            ticketAddReq.setOrderId(orderId);
            ticketAddReq.setSuitablePeople(scenicDTO.getApplicableCrowdName());
            List<SupplierSystemOrderAdmissionTicketDetailAddReq> ticketDetailAddReqList = new LinkedList<>();
            SupplierSystemOrderAdmissionTicketDetailAddReq addReq = new SupplierSystemOrderAdmissionTicketDetailAddReq();
            addReq.setOrderId(orderId);
            addReq.setTicketTypeName(scenicDTO.getTicketName());
            //ticketName单价不能为空
            addReq.setUnitPrice(new BigDecimal("1.0"));
            addReq.setNumber(scenicDTO.getTicketNumber());
            //旅客json不能为空
            addReq.setPassengerJson("");
            ticketDetailAddReqList.add(addReq);
            ticketAddReq.setSupplierSystemOrderAdmissionTicketDetailAddReqList(ticketDetailAddReqList);
            ticketAddReqList.add(ticketAddReq);
            admissionAddReq.setSupplierSystemOrderAdmissionAddReqList(ticketAddReqList);
            supplierOrderService.addSystemAdmission(admissionAddReq, tokenUser.getId());

        }

    }

    /* @MethodName: 动态套票 下各自订单后 确认对应状态
     * @Description: TODO
     * @Param:
     * @Return:
     * @Author: 杨林
     * @Date:2021/4/14 10:57
     **/
    @Override
    public void changeAffirmState(Long orderId, Integer isAffirm) {
        UpdateWrapper<SeasonProductOrderScenic> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().eq(SeasonProductOrderScenic::getOrderId, orderId);
        updateWrapper.lambda().set(SeasonProductOrderScenic::getScheduledStatus, isAffirm);
        orderScenicMapper.update(null, updateWrapper);
    }


    /* @MethodName: 退款状态
     * @Description: TODO
     * @Param:
     * @Return:
     * @Author: 杨林
     * @Date:2021/4/20 10:25
     **/
    @Override
    public void changeCancelOrderState(Long orderId, Integer cancelStatus) {
        UpdateWrapper<SeasonProductOrderScenic> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().eq(SeasonProductOrderScenic::getOrderId, orderId);
        updateWrapper.lambda().set(SeasonProductOrderScenic::getCancelStatus, cancelStatus);
        orderScenicMapper.update(null, updateWrapper);
    }

    /* @MethodName: 固定套票下单 走景点门票的 下单接口
     * @Description: TODO
     * @Param:
     * @Return:
     * @Author: 杨林
     * @Date:2021/4/21 13:56
     **/
    @Override
    public void playScenicOrder(TokenUser user, List<SeasonOrderPayDTO> payList, List<SeasonOrderTouristDataDTO> touristList, Map<String, Object> map) {
        SeasonOrder seasonOrder = (SeasonOrder) map.get("seasonOrder");//获取订单信息
        List<SeasonProductOrderScenicDTO> list = getOrderScenicList(seasonOrder.getId());
        List<Long> orderIds = new ArrayList<>();
        if (null != list && list.size() > 0) {
            for (SeasonProductOrderScenicDTO l : list) {
                ScenicProductPriceListReq scenicReq = new ScenicProductPriceListReq();
                scenicReq.setProductId(l.getProductId());
                scenicReq.setTime(l.getTicketDate());
                scenicReq.setUserId(user.getId());
                BigDecimal totalProductPrice = BigDecimal.ZERO;
                BigDecimal couponDeduction = BigDecimal.ZERO;
                List<ScenicProductPriceListDTO> resultList = scenicProductService.scenicProductPriceList(scenicReq);

                ScenicProductPriceListDTO dto = new ScenicProductPriceListDTO();
                if (null != resultList && resultList.size() > 0) {
                    dto = resultList.stream().findFirst().get();
                    BigDecimal productPrice = dto.getPrice().add(dto.getReserveCharge());
                    totalProductPrice = productPrice.multiply(new BigDecimal(l.getTicketNumber()));
                }
                //景点信息下单
                ScenicOrderInputCheckReq scenicOrderInputCheckReq = new ScenicOrderInputCheckReq();
                scenicOrderInputCheckReq.setProductId(l.getProductId());//产品
                scenicOrderInputCheckReq.setNum(l.getTicketNumber());//票数
                scenicOrderInputCheckReq.setSingleTicketFee(l.getProductPrice());//价格
                scenicOrderInputCheckReq.setFee(dto.getReserveCharge());
                scenicOrderInputCheckReq.setServiceNum(l.getTicketNumber());
                List<ScenicOrderTouristInputCheckReq> touristInfos = new ArrayList<>();
                if (null != touristList && touristList.size() > 0) {
                    touristList.forEach(tourist -> {
                        //转换旅客信息 并添加
                        touristInfos.add(EntityUtil.convertBean(tourist, ScenicOrderTouristInputCheckReq.class));
                    });
                }
                List<ScenicPayOrderCollectionReq> reqList = new ArrayList<>();//付款的集合
                //推广码信息
                boolean couponFlag = (boolean) map.get("couponFlag");//获取推广码使用标识
                if (!couponFlag && StringUtils.isNotBlank(seasonOrder.getCouponCode())) {
                    OperateBankConformQueryReq operateBankConformQueryReq = new OperateBankConformQueryReq();
                    operateBankConformQueryReq.setId(Long.parseLong(seasonOrder.getCouponCode()));//编码
                    operateBankConformQueryReq.setBusinessType(SystemBusinessType.ATTRACTION_TICKET.getCode());//类型
                    operateBankConformQueryReq.setChannelId(1L);//使用渠道，1代表云平台
                    operateBankConformQueryReq.setRelationId(l.getProductId());
                    operateBankConformQueryReq.setTotalPaidIn(totalProductPrice);//价格
                    CrmMemberQueryReq crmMemberQueryReq = new CrmMemberQueryReq();
                    crmMemberQueryReq.setQueryType(1);
                    crmMemberQueryReq.setNumber(String.valueOf(seasonOrder.getMemberId()));
                    CrmAccountDTO crmAccountDTO = crmMemberService.queryAccountDetail(crmMemberQueryReq);
                    operateBankConformQueryReq.setDiscountObjectId((long) crmAccountDTO.getType());
                    Result<OperateBankPreferenceQueryDTO> conform = iOperateBankPreferenceService.queryConform(operateBankConformQueryReq);
                    if (conform.isSuccess()) {
                        map.put("couponFlag", true);
                        scenicOrderInputCheckReq.setCouponCode(seasonOrder.getCouponCode());
                        scenicOrderInputCheckReq.setCouponDeduction(conform.getData().getReductionAmount());
                        couponDeduction.add(conform.getData().getReductionAmount());
                        //添加推广码的付款方式
                        ScenicPayOrderCollectionReq scenicPOCReq = new ScenicPayOrderCollectionReq();
                        scenicPOCReq.setCollectionWay(PayRefundMethod.TGM.getCode());
                        scenicPOCReq.setCollectionAmount(conform.getData().getReductionAmount());
                        reqList.add(scenicPOCReq);
                    }
                }
                //积分
                BigDecimal usingPoints = (BigDecimal) map.get("usingPoints");//获取积分使用标识
                if (usingPoints.compareTo(BigDecimal.ZERO) > 0) {
                    //添加积分的付款方式
                    ScenicPayOrderCollectionReq scenicPOCReq = new ScenicPayOrderCollectionReq();
                    if (totalProductPrice.compareTo(usingPoints) >= 0) {
                        map.put("usingPoints", BigDecimal.ZERO);//全部使用了使用则没有了
                        scenicOrderInputCheckReq.setIntegral(usingPoints.multiply(new BigDecimal(100)).intValue());
                        scenicOrderInputCheckReq.setIntegralDeduction(usingPoints);
                        couponDeduction.add(usingPoints);
                        scenicPOCReq.setCollectionAmount(usingPoints);
                    } else {
                        map.put("usingPoints", usingPoints.subtract(totalProductPrice));//添加积分使用之后剩余的积分
                        scenicOrderInputCheckReq.setIntegral(totalProductPrice.multiply(new BigDecimal(100)).intValue());
                        scenicOrderInputCheckReq.setIntegralDeduction(totalProductPrice);
                        couponDeduction.add(totalProductPrice);
                        scenicPOCReq.setCollectionAmount(totalProductPrice);
                    }
                    scenicPOCReq.setCollectionWay(PayRefundMethod.CRM.getCode());
                    reqList.add(scenicPOCReq);
                }
                ScenicAddCheckOrderReq scenicAddCheckOrderReq = new ScenicAddCheckOrderReq();
                scenicAddCheckOrderReq.setScenicOrderInputCheckReq(scenicOrderInputCheckReq);
                scenicAddCheckOrderReq.setTouristInfos(touristInfos);
                //去下订单
                Result<Long> addResult = scenicOrderService.addOrderInfo(scenicAddCheckOrderReq, user.getId());
                if (!addResult.isSuccess()) {//下单失败
                    map.put("scenicAddOrderResult", addResult);
                    map.put("failFlag", true);
                    return;
                }
                orderIds.add(addResult.getData());
                BigDecimal receivableAmount = totalProductPrice.subtract(couponDeduction);
                //根据支付方式计算价格
                if (receivableAmount.compareTo(BigDecimal.ZERO) >= 0) {
                    boolean isFinal = (boolean) map.get("isFinal");
                    for (SeasonOrderPayDTO pay : payList) {
                        BigDecimal collectionAmount = pay.getCollectionAmount();//当前支付的价格
                        if (collectionAmount.compareTo(BigDecimal.ZERO) == 0) {
                            continue;
                        }
                        ScenicPayOrderCollectionReq scenicPayOrderReq = EntityUtil.convertBean(pay, ScenicPayOrderCollectionReq.class);
                        scenicPayOrderReq.setOrderId(addResult.getData());
                        if (!isFinal) {
                            //门市汇率
                          //  BigDecimal marketExchangeRate = packageService.getMarketExchangeRate(pay.getCurrencyId());
                          //  BigDecimal payPrice = marketExchangeRate.multiply(collectionAmount);//当前支付的价格转换成港币
                            if (collectionAmount.compareTo(receivableAmount) >= 0) {
                               // BigDecimal currentPrice = receivableAmount.divide(marketExchangeRate, 2, BigDecimal.ROUND_UP);
                                if (collectionAmount.compareTo(collectionAmount) >= 0) {
                                    //结余之后的价格
                                    pay.setCollectionAmount(BigDecimal.ZERO);
                                } else {
                                    //当前币种的价格
                                    scenicPayOrderReq.setCollectionAmount(collectionAmount);
                                    //结余之后的价格
                                    pay.setCollectionAmount(collectionAmount.subtract(collectionAmount));
                                }
                                break;
                            } else {
                                //全部抵扣就变成零
                                pay.setCollectionAmount(BigDecimal.ZERO);
                            }
                        } else {
                            //全部抵扣就变成零
                            pay.setCollectionAmount(BigDecimal.ZERO);
                        }
                        reqList.add(scenicPayOrderReq);
                    }
                }
                Result payResult = scenicOrderService.payOrder(reqList, user.getId());
                if (!payResult.isSuccess()) {//支付失败
                    map.put("scenicPayOrderResult", payResult);
                    map.put("failFlag", true);
                }else {
                    SeasonProductOrderScenic scenic =EntityUtil.convertBean(l, SeasonProductOrderScenic.class);
                    Long scenicId = SnowflakeIdWorker.nextId();
                    scenic.setId(scenicId);
                    scenic.setSeasonOrderId(seasonOrder.getId());
                    scenic.setOrderId(addResult.getData());
                    scenic.setCancelStatus(1);
                    scenic.setScheduledStatus(2);
                    orderScenicMapper.insert(scenic);
                }
            }
            map.put("scenicOrderIds", orderIds);
        }
    }


    /* @MethodName: 固定套票下单 走 内部挂账形式
     * @Description: TODO
     * @Param:
     * @Return:
     * @Author: 杨林
     * @Date:2021/4/21 14:00
     **/
    @Override
    public void playInternalOrder(Long orderId, TokenUser user, List<SeasonOrderTouristDataDTO> touristList) {

    }

    public SeasonOrder getSeasonOrderById(Long id) {
        return seasonOrderMapper.selectById(id);
    }
}
